﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Profile.cs" company="">
//   
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace ExecutionTool.Profile
{
    using System.Runtime.Serialization;
    using System.Text.RegularExpressions;

    [DataContract]
    public class Profile
    {
        #region Public Properties

        [DataMember]
        public string Description { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public Orchestration Orchestration { get; set; }

        [DataMember]
        public SqlAzureLocation Source { get; set; }

        [DataMember]
        public AzureStorageLocation TargetAzureStorage { get; set; }

        [DataMember]
        public OnPremisesLocation TargetOnPremisesLocation { get; set; }

        [DataMember]
        public SqlAzureLocation TargetSqlAzureVerification { get; set; }

        #endregion

        #region Public Methods and Operators

        public void Validate()
        {
            this.ValidateProfileName();

            this.ValidateSqlAzureLocation(this.Source, true);

            if (!this.Orchestration.CopyDatabase && !this.Orchestration.Export)
            {
                throw new ValidationException("At least copy database or export or both of them must be specified.", this.Name);
            }

            if (this.Orchestration.Export)
            {
                this.ValidateTargetAzureStorage();

                if (this.Orchestration.VerifyExport)
                {
                    this.ValidateSqlAzureLocation(this.TargetSqlAzureVerification, false);
                }

                if (this.Orchestration.CopyToOnPremises)
                {
                    this.ValidateOnPremisesLocation();
                }
            }
            else
            {
                if (this.Orchestration.VerifyExport || this.Orchestration.CopyToOnPremises)
                {
                    throw new ValidationException(
                        "Export must be enabled first to enable export verification and/or copy to on-premises location.", this.Name);
                }
            }
        }

        #endregion

        #region Methods

        private void ValidateOnPremisesLocation()
        {
            if (this.TargetOnPremisesLocation == null)
            {
                throw new ValidationException("The target on-premises location must be specified.", this.Name);
            }

            if (string.IsNullOrWhiteSpace(this.TargetOnPremisesLocation.Location))
            {
                throw new ValidationException("The folder name of the target on-premises location must be specified.", this.Name);
            }
        }

        private void ValidateProfileName()
        {
            // since the storage container name will be in format [dbname-profilename], here we will only allow names with less than 40 characters
            const string ProfileNameRegEx = @"^(([a-z\d]((-(?=[a-z\d]))|([a-z\d])){1,40})|(\$root))$";
            if (string.IsNullOrWhiteSpace(this.Name) || !Regex.IsMatch(this.Name, ProfileNameRegEx))
            {
                throw new ValidationException(
                    "The profile name is invalid. Only lowercase letters, numbers and incontinuous dash is allowed. The name must be less than 40 characters.", 
                    this.Name);
            }
        }

        private void ValidateSqlAzureLocation(SqlAzureLocation sqlAzureLocation, bool sourceLocation)
        {
            string whichSqlAzureLocation;

            if (sourceLocation)
            {
                whichSqlAzureLocation = "source";
            }
            else
            {
                whichSqlAzureLocation = "export verification";
            }

            if (sqlAzureLocation == null)
            {
                throw new ValidationException(string.Format("The {0} SQL Azure location must be specified.", whichSqlAzureLocation), this.Name);
            }

            if (string.IsNullOrWhiteSpace(sqlAzureLocation.ServerNamePrefix))
            {
                throw new ValidationException(
                    string.Format("The server name of the {0} SQL Azure location must be specified.", whichSqlAzureLocation), this.Name);
            }

            if (string.IsNullOrWhiteSpace(sqlAzureLocation.UserName))
            {
                throw new ValidationException(
                    string.Format("The user name of the {0} SQL Azure location must be specified.", whichSqlAzureLocation), this.Name);
            }

            if (string.IsNullOrWhiteSpace(sqlAzureLocation.Password))
            {
                throw new ValidationException(
                    string.Format("The password of the {0} SQL Azure location must be specified.", whichSqlAzureLocation), this.Name);
            }

            if (sourceLocation && string.IsNullOrWhiteSpace(sqlAzureLocation.DatabaseName))
            {
                throw new ValidationException(
                    string.Format("The database name of the {0} SQL Azure location must be specified.", whichSqlAzureLocation), this.Name);
            }
        }

        private void ValidateTargetAzureStorage()
        {
            if (this.TargetAzureStorage == null)
            {
                throw new ValidationException("The target Azure storage must be specifed.", this.Name);
            }

            if (string.IsNullOrWhiteSpace(this.TargetAzureStorage.StorageAccount))
            {
                throw new ValidationException("The account name of the target Azure storage must be specified.", this.Name);
            }

            if (string.IsNullOrWhiteSpace(this.TargetAzureStorage.AccessKey))
            {
                throw new ValidationException("The access key of the target Azure storage must be specified.", this.Name);
            }
        }

        #endregion
    }
}
